
#include "../app_status_bar_conf.h"
#include "../inc/app_status_bar_type.h"

#if STATUS_BAR_APP_USE


#define APP_NAME "状态栏"
#define AUTHOR "启凡科创"
#define VERSION "1.0.0"

LV_FONT_DECLARE(app_status_bar_font10_reg);
LV_FONT_DECLARE(app_status_bar_font14_reg);
LV_FONT_DECLARE(app_status_bar_font16_reg);

static app_status_bar_scr_objs_t scr_objs;

extern void app_status_bar_widgets_init(void);
extern void app_status_bar_expand_widgets_cb();
extern void app_status_bar_hide_widgets_cb();
extern void app_status_bar_expand_msg_cb();
extern void app_status_bar_hid_msg_end_cb();
extern void app_status_bar_hid_msg_start_cb();
extern void app_status_bar_control_init(void);
extern void app_status_bar_control_expand_start();
extern void app_status_bar_control_hid_start();

#if STATUS_BAR_USE_NOTIFICATION || STATUS_BAR_USE_CONTROL_CENTER
static void create_page();

/**
 * @brief 获取控制中心空间位置
 *
 * @param x 保存结果
 * @param y 保存结果
 * @param dx 定义的x
 * @param dy 定义的y
 */

#if STATUS_BAR_USE_WIFI_LIST || STATUS_BAR_USE_BT_LIST
static void get_widgets_define_pos(lv_coord_t *x, lv_coord_t *y, lv_coord_t dx, lv_coord_t dy)
{
    *x = dx;
    *y = dy;
}
#endif
#endif

app_status_bar_scr_objs_t *app_status_bar_get_objs()
{
    return &scr_objs;
}

/**
 * @brief 动画结束隐藏动画对象
 *
 * @param e
 */
static void anim_end_hid_cb(lv_anim_t *e)
{
    lv_obj_add_flag((lv_obj_t *)e->var, LV_OBJ_FLAG_HIDDEN);
}

#if STATUS_BAR_USE_NOTIFICATION && STATUS_BAR_USE_CONTROL_CENTER
/**
 * @brief 信息页展开关闭回调
 *
 * @param e
 */
static void anim_notifacation_cb(lv_anim_t *e)
{

    if (scr_objs.focus_page == scr_objs.notification)
        app_status_bar_expand_msg_cb();
    else
        app_status_bar_hid_msg_end_cb();
}
#endif

/**
 * @brief 展开状态栏结束回调
 *
 * @param e
 */
static void expand_end_cb(lv_anim_t *e)
{
    if (scr_objs.expand != STATUS_BAR_EXPAND)
        return;
    app_status_bar_expand_widgets_cb();
#if STATUS_BAR_USE_NOTIFICATION
    if (scr_objs.focus_page == scr_objs.notification)
        app_status_bar_expand_msg_cb();
#endif
}

/**
 * @brief 是否隐藏状态栏
 *
 * @param arg 0:隐藏 1:显示
 * @param size 255：内部调用，不处理全屏状态，其他：处理全屏状态
 */
static void status_bar_show_en_cb(void *arg, size_t size)
{
    uint8_t sta = *(uint8_t *)arg;
    lv_coord_t start = 0, end = 0, time = 0;
    lv_anim_t a;
    lv_anim_init(&a);

    if (sta) // 显示
    {
        if (size != 255 && scr_objs.full_screen_en == 1)
        {
            scr_objs.full_screen_en = 0;
            if (scr_objs.hid_timer != NULL)
            {
                lv_timer_del(scr_objs.hid_timer);
                scr_objs.hid_timer = NULL;
            }
        }

        if (scr_objs.expand > STATUS_BAR_HIDDEN)
            return;
        scr_objs.expand = STATUS_BAR_INFO;
        lv_obj_clear_flag(scr_objs.bar_left, LV_OBJ_FLAG_HIDDEN);
        lv_obj_clear_flag(scr_objs.bar_right, LV_OBJ_FLAG_HIDDEN);

        start = lv_obj_get_y(scr_objs.bar_left);
        end = 0;
        time = (0 - start) * 10;
    }
    else
    {
        if (size != 255 && scr_objs.full_screen_en == 0)
        {
            scr_objs.full_screen_en = 1;
        }

        if (scr_objs.expand == STATUS_BAR_HIDDEN)
            return;
        scr_objs.expand = STATUS_BAR_HIDDEN;

        start = lv_obj_get_y(scr_objs.bar_left);
        end = -STATUS_BAR_HEIGHT;
        time = (start + STATUS_BAR_HEIGHT) * 10;
    }

    lv_anim_set_var(&a, scr_objs.bar_left);
    lv_anim_set_values(&a, start, end);
    lv_anim_set_time(&a, time);
    lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_y);
    if (!sta)
        lv_anim_set_deleted_cb(&a, anim_end_hid_cb);
    lv_anim_start(&a);

    if (sta)
        lv_anim_set_deleted_cb(&a, expand_end_cb);
    lv_anim_set_var(&a, scr_objs.bar_right);
    lv_anim_start(&a);
}

/**
 * @brief 自动隐藏定时器回调
 *
 * @param e
 */
static void hid_timer_cb(lv_timer_t *e)
{
    lv_timer_del(e);
    scr_objs.hid_timer = NULL;
    if (scr_objs.expand != STATUS_BAR_INFO)
        return;
    uint8_t sta = 0;
    status_bar_show_en_cb(&sta, 255);
}

#if !STATUS_BAR_USE_TOPIC_MESSENGER
void status_bar_show_en(bool en)
{
    status_bar_show_en_cb((void *)&en, 1);
}
#endif

#if STATUS_BAR_USE_NOTIFICATION || STATUS_BAR_USE_CONTROL_CENTER
/**
 * @brief 设置对象透明度回调
 *
 * @param obj 对象
 * @param opa 透明度
 */
static void lv_obj_set_opa(lv_obj_t *obj, lv_coord_t opa)
{

#if STATUS_BAR_USE_IMG_BACKGROUND
    lv_obj_t *img = lv_obj_get_child(scr_objs.scr, 0);

    if (img == NULL)
    {
#endif // STATUS_BAR_USE_IMG_BACKGROUND
        lv_obj_set_style_bg_opa(obj, opa, 0);
#if STATUS_BAR_USE_IMG_BACKGROUND
    }
    else
    {
#if STATUS_BAR_IMG_FULL
        lv_obj_set_style_img_opa(img, opa, 0);
#else
        lv_obj_set_style_img_opa(img, opa / 10, 0);
        lv_obj_set_style_bg_opa(img, opa, 0);
#endif // STATUS_BAR_IMG_FULL
    }
#endif // STATUS_BAR_USE_IMG_BACKGROUND
    if (opa == 0)
    {
        lv_obj_add_flag(obj, LV_OBJ_FLAG_HIDDEN);
#if STATUS_BAR_USE_NOTIFICATION
        lv_obj_add_flag(scr_objs.notification, LV_OBJ_FLAG_HIDDEN);
#endif
#if STATUS_BAR_USE_CONTROL_CENTER
        lv_obj_add_flag(scr_objs.control_center, LV_OBJ_FLAG_HIDDEN);
#endif

#if STATUS_BAR_USE_IMG_BACKGROUND
        if (img != NULL)
        {

            const lv_img_dsc_t *img_src = lv_img_get_src(img);
            lv_obj_del(img); // lv_color_mix()
#if STATUS_BAR_IMG_FULL
            lv_snapshot_free((void *)img_src);
#else
            lv_mem_free((void *)img_src->data);
            lv_mem_free((void *)img_src);
#endif // STATUS_BAR_IMG_FULL
        }
#endif // STATUS_BAR_USE_IMG_BACKGROUND

#if STATUS_BAR_USE_NOTIFICATION
        if (scr_objs.focus_page == scr_objs.notification)
            app_status_bar_hid_msg_end_cb();
#endif
        scr_objs.expand = STATUS_BAR_INFO;
        if (scr_objs.hid_timer != NULL)
        {
            lv_timer_reset(scr_objs.hid_timer);
        }
        else if (scr_objs.full_screen_en)
        {
            scr_objs.hid_timer = lv_timer_create(hid_timer_cb, 3000, NULL);
        }
    }
}

#if STATUS_BAR_USE_IMG_BACKGROUND
static lv_img_dsc_t *lv_get_blur_scr()
{
    lv_img_dsc_t *img = lv_mem_alloc(sizeof(lv_img_dsc_t));
    if (img != NULL)
    {
        uint8_t *bmp_small = lv_mem_alloc(LV_HOR_RES * LV_VER_RES * sizeof(lv_color_t) / (STATUS_BAR_PROPORTION * STATUS_BAR_PROPORTION));

        if (bmp_small != NULL)
        {
            lv_img_dsc_t *img_sn = lv_snapshot_take(lv_scr_act(), LV_IMG_CF_TRUE_COLOR);
            if (img_sn != NULL)
            {
                memcpy(img, img_sn, sizeof(lv_img_dsc_t));
                size_t cow_cnt = 0;

                lv_color_t *data = (lv_color_t *)img_sn->data;
                lv_color_t *small = (lv_color_t *)bmp_small;

                for (size_t i = 0; i < (LV_HOR_RES * LV_VER_RES / (STATUS_BAR_PROPORTION * STATUS_BAR_PROPORTION)); i++)
                {
#if STATUS_BAR_COLOR_MIX

                    lv_color_t *data_tmp = data;
                    lv_color_t tmp = *data;

                    for (size_t cow = 0; cow < STATUS_BAR_PROPORTION; cow++)
                    {
                        for (size_t line = 0; line < STATUS_BAR_PROPORTION; line++)
                        {
                            tmp = lv_color_mix(*data_tmp++, tmp, 127);
                        }
                        data_tmp += LV_HOR_RES * sizeof(lv_color_t) - STATUS_BAR_PROPORTION;
                    }

                    *small++ = tmp;

                    // *small++ = *data;

#else
                    *small++ = *data;
#endif                                             // STATUS_BAR_COLOR_MIX
                    data += STATUS_BAR_PROPORTION; // * 2;
                    cow_cnt++;
                    if (cow_cnt == LV_HOR_RES / STATUS_BAR_PROPORTION)
                    {
                        cow_cnt = 0;
                        data += LV_HOR_RES * (STATUS_BAR_PROPORTION - 1);
                    }
                }

                lv_snapshot_free(img_sn);

                img->data = bmp_small;
                img->header.h = LV_VER_RES / STATUS_BAR_PROPORTION;
                img->header.w = LV_HOR_RES / STATUS_BAR_PROPORTION;

#if STATUS_BAR_IMG_FULL

                lv_obj_t *scr_img = lv_img_create(scr_objs.scr);
                lv_img_set_src(scr_img, img);
                lv_img_set_zoom(scr_img, 256 * STATUS_BAR_PROPORTION + 1);
#if STATUS_BAR_ANTIALIAS
                lv_img_set_antialias(scr_img, true);
#else
                lv_img_set_antialias(scr_img, false);
#endif // STATUS_BAR_ANTIALIAS
                lv_obj_align(scr_img, LV_ALIGN_CENTER, 0, 0);
                lv_obj_set_style_bg_color(scr_img, lv_obj_get_style_bg_color(scr_objs.scr, 0), 0);
                lv_obj_set_style_bg_opa(scr_img, 255, 0);
                lv_obj_set_style_img_opa(scr_img, 255 / 10, 0);
                img_sn = lv_snapshot_take(scr_objs.scr, LV_IMG_CF_TRUE_COLOR);
                lv_mem_free((void *)img->data);
                lv_mem_free((void *)img);
                img = img_sn;
                lv_obj_del(scr_img);
#endif // STATUS_BAR_IMG_FULL
            }
            else
            {
                lv_mem_free(img);
                lv_mem_free(bmp_small);
                img = NULL;
            }
        }
        else
        {
            lv_mem_free(img);
            img = NULL;
        }
    }
    return img;
}
#endif // STATUS_BAR_USE_IMG_BACKGROUND
#endif // #if (STATUS_BAR_USE_NOTIFICATION || STATUS_BAR_USE_CONTROL_CENTER)

#if (STATUS_BAR_USE_NOTIFICATION || STATUS_BAR_USE_CONTROL_CENTER)
static void status_bar_close_cb(void *arg, size_t len)
{
    uint8_t sta = *(uint8_t *)arg;
    if (sta > 2)
        return;

    if (sta == 0 && scr_objs.expand != STATUS_BAR_EXPAND)
        return;
    if (sta && scr_objs.expand == STATUS_BAR_EXPAND)
        return;

    lv_coord_t start = 0, end = 0;
    lv_anim_t a;
    lv_anim_init(&a);
    lv_anim_set_time(&a, 200);

    if (sta) // 展开
    {
#if !STATUS_BAR_USE_NOTIFICATION
        sta = 2;
#endif
#if !STATUS_BAR_USE_CONTROL_CENTER
        sta = 1;
#endif
        start = -(LV_VER_RES - STATUS_BAR_HEIGHT);
        end = STATUS_BAR_HEIGHT;
        if (scr_objs.expand == STATUS_BAR_HIDDEN) // 隐藏中
        {
            uint8_t tmp = 1;
            status_bar_show_en_cb(&tmp, 255);
        }
        scr_objs.expand = STATUS_BAR_EXPAND;
#if STATUS_BAR_USE_IMG_BACKGROUND
        lv_img_dsc_t *img = lv_get_blur_scr();

        if (img != NULL)
        {
            lv_obj_t *scr_img = lv_img_create(scr_objs.scr);
            lv_img_set_src(scr_img, img);
#if !STATUS_BAR_IMG_FULL
            lv_img_set_zoom(scr_img, 256 * STATUS_BAR_PROPORTION + 1);
            lv_obj_set_style_bg_color(scr_img, lv_obj_get_style_bg_color(scr_objs.scr, 0), 0);
#if STATUS_BAR_ANTIALIAS
            lv_img_set_antialias(scr_img, true);
#else
            lv_img_set_antialias(scr_img, false);
#endif // STATUS_BAR_ANTIALIAS
#endif // !STATUS_BAR_IMG_FULL
            lv_obj_align(scr_img, LV_ALIGN_CENTER, 0, 0);
        }
#endif // STATUS_BAR_USE_IMG_BACKGROUND
        lv_obj_clear_flag(scr_objs.scr, LV_OBJ_FLAG_HIDDEN);
#if STATUS_BAR_USE_NOTIFICATION
        lv_obj_clear_flag(scr_objs.notification, LV_OBJ_FLAG_HIDDEN);
#endif
#if STATUS_BAR_USE_CONTROL_CENTER
        lv_obj_clear_flag(scr_objs.control_center, LV_OBJ_FLAG_HIDDEN);
#endif
    }

    if (sta == 0) // 隐藏
    {
        scr_objs.expand = STATUS_BAR_HIDDEN;
        app_status_bar_hide_widgets_cb();
#if STATUS_BAR_USE_NOTIFICATION
        if (scr_objs.focus_page == scr_objs.notification)
            app_status_bar_hid_msg_start_cb();
#endif
#if STATUS_BAR_USE_CONTROL_CENTER
        if (scr_objs.focus_page == scr_objs.control_center)
            app_status_bar_control_hid_start();
#endif
        start = STATUS_BAR_HEIGHT;
        end = -(LV_VER_RES - STATUS_BAR_HEIGHT);
    }
#if STATUS_BAR_USE_NOTIFICATION
    else if (sta == 1) // 展开信息中心
    {
        scr_objs.focus_page = scr_objs.notification;
        // app_status_bar_expand_msg_cb();
        lv_anim_set_var(&a, scr_objs.notification);
        lv_obj_set_x(scr_objs.notification, 0);
#if STATUS_BAR_USE_CONTROL_CENTER
        lv_obj_set_pos(scr_objs.control_center, LV_HOR_RES, STATUS_BAR_HEIGHT);
        lv_obj_scroll_to_y(scr_objs.control_center, 0, LV_ANIM_OFF);
#endif
    }
#endif
#if STATUS_BAR_USE_CONTROL_CENTER
    else if (sta == 2) // 展开控制中心
    {
        app_status_bar_control_expand_start();
        scr_objs.focus_page = scr_objs.control_center;
        lv_obj_set_x(scr_objs.control_center, 0);
#if STATUS_BAR_USE_NOTIFICATION
        lv_obj_set_pos(scr_objs.notification, -LV_HOR_RES, STATUS_BAR_HEIGHT);
        lv_obj_scroll_to_y(scr_objs.notification, 0, LV_ANIM_OFF);
#endif
    }
#endif

    lv_obj_scroll_to_y(scr_objs.focus_page, 0, LV_ANIM_OFF);

    lv_anim_set_var(&a, scr_objs.focus_page);
    lv_anim_set_values(&a, start, end);
    lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_y);
    lv_anim_start(&a);

    lv_anim_set_var(&a, scr_objs.scr);
    if (sta)
    {
        lv_anim_set_values(&a, 1, 255);
        lv_anim_set_deleted_cb(&a, expand_end_cb);
    }
    else
    {
        lv_anim_set_values(&a, 255, 0);
    }
    lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_opa);
    lv_anim_start(&a);
}

void status_bar_expand(bool en)
{
    status_bar_close_cb(&en, 1);
}

#endif

#if STATUS_BAR_BG_OPA
static void touch_bar_bg_opa_cb(lv_anim_t *a)
{
    lv_obj_set_style_bg_opa(scr_objs.touch_bar, 0, 0);
    lv_obj_set_height(scr_objs.touch_bar, STATUS_BAR_HEIGHT);
}
#endif

static void event_cb(lv_event_t *e)
{
    lv_indev_t *indev = lv_event_get_indev(e);
    static lv_point_t start_p;

#if (STATUS_BAR_USE_NOTIFICATION && STATUS_BAR_USE_CONTROL_CENTER)
    static lv_point_t last_point;
#endif // STATUS_BAR_USE_NOTIFICATION && STATUS_BAR_USE_CONTROL_CENTER
    static int16_t move = 0;
    static uint8_t touch_en = 1;

    if (e->code == LV_EVENT_PRESSED)
    {
        lv_indev_get_point(indev, &start_p);
#if (STATUS_BAR_USE_NOTIFICATION || STATUS_BAR_USE_CONTROL_CENTER)
        scr_objs.dir = LV_DIR_NONE;
#endif
#if (STATUS_BAR_USE_NOTIFICATION && STATUS_BAR_USE_CONTROL_CENTER)
        last_point = start_p;
#endif // STATUS_BAR_USE_NOTIFICATION && STATUS_BAR_USE_CONTROL_CENTER

        if (e->target == scr_objs.touch_bar && scr_objs.expand == STATUS_BAR_HIDDEN)
            touch_en = 0;
        else
            touch_en = 1;
        return;
    }

    if (e->code == LV_EVENT_PRESSING)
    {
        if (e->target == scr_objs.touch_bar) // bar
        {

            if (scr_objs.expand == STATUS_BAR_EXPAND)
                return;
            if (touch_en == 2)
                return;

            if (move < STATUS_BAR_EXPAND_MOVE)
            {
                lv_point_t p;
                lv_indev_get_point(indev, &p);
                move = p.y - start_p.y;
                if (move >= STATUS_BAR_EXPAND_MOVE) // 展开
                {
                    move = STATUS_BAR_EXPAND_MOVE;

                    if (scr_objs.expand == STATUS_BAR_HIDDEN) // 隐藏中
                    {
                        uint8_t sta = 1;
                        status_bar_show_en_cb(&sta, 255);
                        scr_objs.hid_timer = lv_timer_create(hid_timer_cb, 3000, NULL);
                        touch_en = 2;
                        return;
                    }
                    else if (scr_objs.hid_timer != NULL)
                    {
                        lv_timer_reset(scr_objs.hid_timer);
                    }

#if (STATUS_BAR_USE_NOTIFICATION || STATUS_BAR_USE_CONTROL_CENTER)

                    if (scr_objs.expand != STATUS_BAR_INFO)
                        return;

                    lv_event_send(scr_objs.touch_bar, LV_EVENT_RELEASED, NULL);

                    uint8_t page = 2;
#if STATUS_BAR_USE_NOTIFICATION && STATUS_BAR_USE_CONTROL_CENTER
                    if (start_p.x < LV_HOR_RES / 2)
                        page = 1;
#elif STATUS_BAR_USE_NOTIFICATION
                    page = 1;
#endif // STATUS_BAR_USE_NOTIFICATION && STATUS_BAR_USE_CONTROL_CENTER

                    status_bar_close_cb(&page, 1);
#endif
                }
#if (STATUS_BAR_USE_NOTIFICATION || STATUS_BAR_USE_CONTROL_CENTER)
                if (touch_en && move)
                {
#if STATUS_BAR_BG_OPA
                    lv_obj_set_style_bg_opa(scr_objs.touch_bar, STATUS_BAR_BG_OPA, 0);
                    lv_obj_set_height(scr_objs.touch_bar, move);
#endif
                    lv_obj_set_y(scr_objs.bar_left, move);
                    lv_obj_set_y(scr_objs.bar_right, move);
                }
#endif
            }
            return;
        }

#if (STATUS_BAR_USE_NOTIFICATION || STATUS_BAR_USE_CONTROL_CENTER)

        if (scr_objs.dir == LV_DIR_ALL)
            return;

        // notification or control_center
        lv_point_t p;
        lv_indev_get_point(indev, &p);

        if (start_p.y >= (LV_VER_RES - STATUS_BAR_HEIGHT - STATUS_BAR_CLOSE_Y_OFFSET)) // 收起
        {
            if ((start_p.y - p.y) < STATUS_BAR_HIDDEN_MOVE)
                return;

            uint8_t sta = 0;

            status_bar_close_cb(&sta, 0);

            move = 0;
            scr_objs.dir = LV_DIR_ALL;
            return;
        }

        // 左右切换
        if (scr_objs.dir == LV_DIR_NONE)
        {
            int16_t tmp = fabs(p.x - start_p.x) - fabs(p.y - start_p.y);
            if (tmp > 0)
            {
                scr_objs.dir = LV_DIR_HOR;
#if (STATUS_BAR_USE_NOTIFICATION && STATUS_BAR_USE_CONTROL_CENTER)
                lv_obj_clear_flag(scr_objs.focus_page, LV_OBJ_FLAG_SCROLLABLE);
#endif
            }
            else if (tmp < 0)
                scr_objs.dir = LV_DIR_VER;
            else
                return;
        }

#if (STATUS_BAR_USE_NOTIFICATION && STATUS_BAR_USE_CONTROL_CENTER)

        if (p.x == last_point.x && p.y == last_point.y)
            return;

        last_point = p;

        if (scr_objs.dir == LV_DIR_HOR)
        {
            lv_obj_set_x(scr_objs.focus_page, (p.x - start_p.x));
            if (scr_objs.focus_page == scr_objs.notification)
                lv_obj_set_x(scr_objs.control_center, LV_HOR_RES + (p.x - start_p.x));
            else
                lv_obj_set_x(scr_objs.notification, -LV_HOR_RES + (p.x - start_p.x));
        }
        return;
#endif // STATUS_BAR_USE_NOTIFICATION && STATUS_BAR_USE_CONTROL_CENTER
#endif // STATUS_BAR_USE_NOTIFICATION || STATUS_BAR_USE_CONTROL_CENTER
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////

    if (e->code == LV_EVENT_RELEASED)
    {

        if (e->target == scr_objs.touch_bar)
        {
            move = 0;
#if (STATUS_BAR_USE_NOTIFICATION || STATUS_BAR_USE_CONTROL_CENTER)
            if (scr_objs.expand == STATUS_BAR_HIDDEN)
                return;

            if (lv_obj_get_y(scr_objs.bar_left) == 0)
                return;

            lv_anim_t a;
            lv_anim_init(&a);
            lv_anim_set_var(&a, scr_objs.bar_left);
            lv_anim_set_values(&a, lv_obj_get_y(scr_objs.bar_left), 0);
            lv_anim_set_time(&a, lv_obj_get_y(scr_objs.bar_left) * 6);
            lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_y);
            lv_anim_start(&a);

            lv_anim_set_var(&a, scr_objs.bar_right);
#if STATUS_BAR_BG_OPA
            lv_anim_set_deleted_cb(&a, touch_bar_bg_opa_cb);
#endif
            lv_anim_start(&a);
#endif
            return;
        }

        //  lv_obj_add_flag(pressed_obj, LV_OBJ_FLAG_CLICKABLE);

#if (STATUS_BAR_USE_NOTIFICATION && STATUS_BAR_USE_CONTROL_CENTER)

        if (scr_objs.dir == LV_DIR_ALL)
            return;

        if (scr_objs.dir == LV_DIR_HOR)
        {

            lv_coord_t x1, x2;

            lv_obj_t *tmp = scr_objs.focus_page;

            lv_obj_add_flag(scr_objs.focus_page, LV_OBJ_FLAG_SCROLLABLE);

            if (lv_obj_get_x(scr_objs.notification) < -(LV_HOR_RES / 2))
            {
                x1 = -LV_HOR_RES;
                x2 = 0;
                scr_objs.focus_page = scr_objs.control_center;
            }
            else
            {
                x1 = 0;
                x2 = LV_HOR_RES;
                scr_objs.focus_page = scr_objs.notification;
            }

            if (tmp != scr_objs.focus_page)
            {
#if STATUS_BAR_USE_NOTIFICATION
                if (scr_objs.focus_page != scr_objs.notification)
                    app_status_bar_hid_msg_start_cb();
#endif
#if STATUS_BAR_USE_CONTROL_CENTER
                if (scr_objs.focus_page == scr_objs.control_center)
                    app_status_bar_control_expand_start();
                else
                    app_status_bar_control_hid_start();
#endif
            }

            lv_anim_t a;
            lv_anim_init(&a);
            lv_anim_set_var(&a, scr_objs.notification);
            lv_anim_set_values(&a, lv_obj_get_x(scr_objs.notification), x1);
            lv_anim_set_time(&a, 200);
            lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_x);
            lv_anim_start(&a);

            lv_anim_set_var(&a, scr_objs.control_center);
            lv_anim_set_values(&a, lv_obj_get_x(scr_objs.control_center), x2);

#if STATUS_BAR_USE_NOTIFICATION
            lv_anim_set_deleted_cb(&a, anim_notifacation_cb);
#endif
            lv_anim_start(&a);
            return;
        }

#endif // STATUS_BAR_USE_NOTIFICATION && STATUS_BAR_USE_CONTROL_CENTER

        return;
    }
}

#if STATUS_BAR_USE_NOTIFICATION || STATUS_BAR_USE_CONTROL_CENTER

static void create_page()
{
    lv_obj_clear_flag(lv_layer_sys(), LV_OBJ_FLAG_SCROLLABLE);

    scr_objs.scr = lv_obj_create(lv_layer_sys());
    lv_obj_set_size(scr_objs.scr, LV_HOR_RES, LV_VER_RES);
    lv_obj_set_style_border_width(scr_objs.scr, 0, 0);
    lv_obj_set_style_radius(scr_objs.scr, 0, 0);
    lv_obj_set_style_bg_opa(scr_objs.scr, LV_OPA_0, 0);
    lv_obj_set_style_bg_color(scr_objs.scr, lv_color_darken(lv_obj_get_style_bg_color(scr_objs.scr, 0), 100), LV_PART_MAIN);
    lv_obj_align(scr_objs.scr, LV_ALIGN_TOP_MID, 0, 0);
    lv_obj_add_flag(scr_objs.scr, LV_OBJ_FLAG_HIDDEN);
    lv_obj_clear_flag(scr_objs.scr, LV_OBJ_FLAG_SCROLLABLE);
    lv_obj_set_style_pad_all(scr_objs.scr, 0, 0);
    lv_obj_clear_flag(scr_objs.scr, LV_OBJ_FLAG_CLICKABLE);

#if STATUS_BAR_USE_NOTIFICATION

    scr_objs.notification = lv_obj_create(lv_layer_sys());
    lv_obj_set_size(scr_objs.notification, LV_HOR_RES, LV_VER_RES - STATUS_BAR_HEIGHT);
    lv_obj_set_scrollbar_mode(scr_objs.notification, LV_SCROLLBAR_MODE_OFF);
    lv_obj_set_style_border_width(scr_objs.notification, 0, 0);
    lv_obj_set_style_bg_opa(scr_objs.notification, LV_OPA_0, 0);
    lv_obj_set_style_radius(scr_objs.notification, 0, 0);
    lv_obj_align(scr_objs.notification, LV_ALIGN_TOP_MID, 0, 0);
    lv_obj_set_y(scr_objs.notification, -(LV_VER_RES - STATUS_BAR_HEIGHT));
    lv_obj_set_style_pad_bottom(scr_objs.notification, STATUS_BAR_NOTIFICATIONS_PAD_BOTTOM, 0);
    lv_obj_set_style_pad_top(scr_objs.notification, STATUS_BAR_NOTIFICATIONS_PA_TOP, 0);

    lv_obj_set_flex_flow(scr_objs.notification, LV_FLEX_FLOW_ROW_WRAP);
    lv_obj_set_style_flex_main_place(scr_objs.notification, LV_FLEX_ALIGN_SPACE_EVENLY, 0);
    lv_obj_set_style_layout(scr_objs.notification, LV_LAYOUT_FLEX, 0);
    lv_obj_set_style_pad_column(scr_objs.notification, STATUS_BAR_CONTROL_CENTER_WIDGETS_SIZE * 0.1, 0);
    lv_obj_set_style_pad_row(scr_objs.notification, STATUS_BAR_CONTROL_CENTER_WIDGETS_SIZE * 0.1, 0);

#endif // STATUS_BAR_USE_NOTIFICATION

#if STATUS_BAR_USE_CONTROL_CENTER

    scr_objs.control_center = lv_obj_create(lv_layer_sys());
    lv_obj_set_size(scr_objs.control_center, LV_HOR_RES, LV_VER_RES - STATUS_BAR_HEIGHT);
    lv_obj_set_scrollbar_mode(scr_objs.control_center, LV_SCROLLBAR_MODE_OFF);
    lv_obj_set_style_border_width(scr_objs.control_center, 0, 0);
    lv_obj_set_style_bg_opa(scr_objs.control_center, LV_OPA_0, 0);
    lv_obj_set_style_radius(scr_objs.control_center, 0, 0);
    lv_obj_align(scr_objs.control_center, LV_ALIGN_TOP_MID, 0, 0);
    lv_obj_set_y(scr_objs.control_center, -(LV_VER_RES - STATUS_BAR_HEIGHT));
    lv_obj_set_style_pad_bottom(scr_objs.control_center, STATUS_BAR_CONTROL_CENTER_WIDGETS_PAD_BOTTOM, 0);
    lv_obj_set_style_pad_top(scr_objs.control_center, STATUS_BAR_CONTROL_CENTER_WIDGETS_PAD_TOP, 0);

    lv_obj_set_style_pad_row(scr_objs.control_center, 0, 0);
    lv_obj_set_style_pad_column(scr_objs.control_center, 0, 0);

    uint16_t wid = STATUS_BAR_CONTROL_CENTER_WIDGETS_SIZE * 0.55;

    static lv_coord_t col_dsc[STATUS_BAR_GRID_COL_NUM + 1];
    static lv_coord_t row_dsc[STATUS_BAR_GRID_ROW_NUM + 1];

    col_dsc[STATUS_BAR_GRID_COL_NUM] = LV_GRID_TEMPLATE_LAST;
    row_dsc[STATUS_BAR_GRID_ROW_NUM] = LV_GRID_TEMPLATE_LAST;

    for (size_t i = 0; i < STATUS_BAR_GRID_COL_NUM; i++)
    {
        col_dsc[i] = wid;
    }
    for (size_t i = 0; i < STATUS_BAR_GRID_ROW_NUM; i++)
    {
        row_dsc[i] = wid;
    }

#if STATUS_BAR_USE_WIFI_LIST || STATUS_BAR_USE_BT_LIST
    lv_coord_t col, row;
#endif

#if STATUS_BAR_USE_WIFI_LIST
    get_widgets_define_pos(&col, &row, APP_STATUS_BAR_WIFI_LIST_POS);
    row_dsc[row] = STATUS_BAR_CONTROL_CENTER_WIDGETS_SIZE * 0.58;
#endif

#if STATUS_BAR_USE_BT_LIST
    get_widgets_define_pos(&col, &row, APP_STATUS_BAR_BT_LIST_POS);
    row_dsc[row] = STATUS_BAR_CONTROL_CENTER_WIDGETS_SIZE * 0.58;
#endif

    lv_obj_set_style_grid_column_dsc_array(scr_objs.control_center, col_dsc, 0);
    lv_obj_set_style_grid_row_dsc_array(scr_objs.control_center, row_dsc, 0);

    lv_obj_set_style_layout(scr_objs.control_center, LV_LAYOUT_GRID, 0);
    lv_obj_set_style_pad_hor(scr_objs.control_center, (LV_HOR_RES - wid * 4) / 2, 0);

#endif // STATUS_BAR_USE_CONTROL_CENTER

#if STATUS_BAR_USE_CONTROL_CENTER
    app_status_bar_control_init();
#endif

#if STATUS_BAR_USE_NOTIFICATION
    lv_obj_add_event_cb(scr_objs.notification, event_cb, LV_EVENT_PRESSED, NULL);
    lv_obj_add_event_cb(scr_objs.notification, event_cb, LV_EVENT_PRESSING, NULL);
    lv_obj_add_event_cb(scr_objs.notification, event_cb, LV_EVENT_RELEASED, NULL);
#endif

#if STATUS_BAR_USE_CONTROL_CENTER
    lv_obj_add_event_cb(scr_objs.control_center, event_cb, LV_EVENT_PRESSED, NULL);
    lv_obj_add_event_cb(scr_objs.control_center, event_cb, LV_EVENT_PRESSING, NULL);
    lv_obj_add_event_cb(scr_objs.control_center, event_cb, LV_EVENT_RELEASED, NULL);
#endif
}

#endif

static void init(void *arg)
{
    scr_objs.hid_timer = NULL;

#if STATUS_BAR_SHOW_DEFULT
    scr_objs.expand = STATUS_BAR_INFO;
    scr_objs.full_screen_en = 0;
#else
    scr_objs.expand = STATUS_BAR_HIDDEN;
    scr_objs.full_screen_en = 1;
#endif

#if (STATUS_BAR_USE_NOTIFICATION || STATUS_BAR_USE_CONTROL_CENTER)
    scr_objs.page_timer = NULL;
    create_page();
#endif // STATUS_BAR_USE_NOTIFICATION || STATUS_BAR_USE_CONTROL_CENTER

    scr_objs.touch_bar = lv_obj_create(lv_layer_sys());
    lv_obj_set_size(scr_objs.touch_bar, LV_HOR_RES, STATUS_BAR_HEIGHT);
    lv_obj_clear_flag(scr_objs.touch_bar, LV_OBJ_FLAG_SCROLLABLE);
    lv_obj_set_style_border_width(scr_objs.touch_bar, 0, 0);
    lv_obj_set_style_radius(scr_objs.touch_bar, 0, 0);
    lv_obj_set_style_bg_opa(scr_objs.touch_bar, LV_OPA_0, 0);
    lv_obj_align(scr_objs.touch_bar, LV_ALIGN_TOP_LEFT, 0, 0);

    lv_obj_set_ext_click_area(scr_objs.touch_bar, STATUS_BAR_OPEN_Y_OFFSET);

    scr_objs.bar_left = lv_obj_create(lv_layer_sys());
    lv_obj_set_size(scr_objs.bar_left, LV_HOR_RES, STATUS_BAR_HEIGHT);
    lv_obj_clear_flag(scr_objs.bar_left, LV_OBJ_FLAG_SCROLLABLE);
    lv_obj_clear_flag(scr_objs.bar_left, LV_OBJ_FLAG_CLICKABLE);
    lv_obj_set_style_border_width(scr_objs.bar_left, 0, 0);
    lv_obj_set_style_radius(scr_objs.bar_left, 0, 0);
    lv_obj_set_style_bg_opa(scr_objs.bar_left, STATUS_BAR_BG_OPA, 0);
    lv_obj_align(scr_objs.bar_left, LV_ALIGN_TOP_LEFT, 0, 0);
    lv_obj_set_style_pad_all(scr_objs.bar_left, 0, 0);
    lv_obj_set_style_pad_left(scr_objs.bar_left, STATUS_BAR_BORDER_SPACE, 0);

    lv_obj_set_flex_flow(scr_objs.bar_left, LV_FLEX_FLOW_ROW);
    lv_obj_set_flex_align(scr_objs.bar_left, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
    lv_obj_set_style_layout(scr_objs.bar_left, LV_LAYOUT_FLEX, 0);
    lv_obj_set_style_pad_column(scr_objs.bar_left, STATUS_BAR_ICON_SPACE, 0);

#if STATUS_BAR_SHOW_DEFULT
    lv_obj_set_y(scr_objs.bar_left, 0);
#else
    lv_obj_set_y(scr_objs.bar_left, -STATUS_BAR_HEIGHT);
#endif // STATUS_BAR_SHOW_DEFULT

    scr_objs.bar_right = lv_obj_create(lv_layer_sys());
    lv_obj_set_size(scr_objs.bar_right, LV_HOR_RES, STATUS_BAR_HEIGHT);
    lv_obj_clear_flag(scr_objs.bar_right, LV_OBJ_FLAG_SCROLLABLE);
    lv_obj_clear_flag(scr_objs.bar_right, LV_OBJ_FLAG_CLICKABLE);
    lv_obj_set_style_border_width(scr_objs.bar_right, 0, 0);
    lv_obj_set_style_radius(scr_objs.bar_right, 0, 0);
    lv_obj_set_style_bg_opa(scr_objs.bar_right, LV_OPA_0, 0);
    lv_obj_align(scr_objs.bar_right, LV_ALIGN_TOP_RIGHT, 0, 0);
    lv_obj_set_style_pad_all(scr_objs.bar_right, 0, 0);
    lv_obj_set_style_pad_right(scr_objs.bar_right, STATUS_BAR_BORDER_SPACE, 0);

    lv_obj_set_flex_flow(scr_objs.bar_right, LV_FLEX_FLOW_ROW_REVERSE);
    lv_obj_set_flex_align(scr_objs.bar_right, LV_FLEX_ALIGN_END, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
    lv_obj_set_style_layout(scr_objs.bar_right, LV_LAYOUT_FLEX, 0);
    lv_obj_set_style_pad_column(scr_objs.bar_right, STATUS_BAR_ICON_SPACE, 0);

#if STATUS_BAR_SHOW_DEFULT
    lv_obj_set_y(scr_objs.bar_right, 0);
#else
    lv_obj_set_y(scr_objs.bar_right, -STATUS_BAR_HEIGHT);
#endif // STATUS_BAR_SHOW_DEFULT

    app_status_bar_widgets_init();

    lv_obj_add_event_cb(scr_objs.touch_bar, event_cb, LV_EVENT_PRESSING, NULL);
    lv_obj_add_event_cb(scr_objs.touch_bar, event_cb, LV_EVENT_PRESSED, NULL);
    lv_obj_add_event_cb(scr_objs.touch_bar, event_cb, LV_EVENT_RELEASED, NULL);

#if STATUS_BAR_USE_TOPIC_MESSENGER
    topic_messenger_subscribe(NULL, "状态栏显示", status_bar_show_en_cb);
#if (STATUS_BAR_USE_NOTIFICATION || STATUS_BAR_USE_CONTROL_CENTER)
    topic_messenger_subscribe(NULL, "状态栏展开", status_bar_close_cb);
#endif
#endif
}

void app_status_bar_register(void)
{
#if STATUS_BAR_USE_APP_MANAGER
    app_manager_register_t cfg;
    app_manager_config_struct_init(&cfg);

    cfg.name = APP_NAME;
    cfg.init = init;
    cfg.author = AUTHOR;
    cfg.ui_type = APP_UI_HAVE;
    cfg.version = VERSION;
    cfg.visible = APP_INVISIBLE;

    app_manager_register_app(&cfg);

#else
    init(NULL);
#endif
}

#endif